package org.xxpay.pay.channel.alizftpay;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.FileItem;
import com.alipay.api.domain.*;
import com.alipay.api.request.AlipayTradeSettleConfirmRequest;
import com.alipay.api.request.AntMerchantExpandIndirectImageUploadRequest;
import com.alipay.api.request.AntMerchantExpandIndirectZftCreateRequest;
import com.alipay.api.request.AntMerchantExpandIndirectZftorderQueryRequest;
import com.alipay.api.response.AlipayTradeSettleConfirmResponse;
import com.alipay.api.response.AntMerchantExpandIndirectImageUploadResponse;
import com.alipay.api.response.AntMerchantExpandIndirectZftCreateResponse;
import com.alipay.api.response.AntMerchantExpandIndirectZftorderQueryResponse;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.xxpay.core.common.constant.MchConstant;
import org.xxpay.core.common.constant.RetEnum;
import org.xxpay.core.common.exception.ServiceException;
import org.xxpay.core.common.util.AmountUtil;
import org.xxpay.core.common.util.FileUtils;
import org.xxpay.core.common.util.MyLog;
import org.xxpay.core.common.util.MySeq;
import org.xxpay.core.entity.*;
import org.xxpay.pay.mq.Mq4AlizftpayTradeSettleConfirm;

import java.net.URL;
import java.util.Arrays;
import java.util.List;

/**
 * @author: dingzhiwei
 * @date: 19/09/04
 * @description: 支付宝相关接口
 */
@Service
public class AlizftpayApiService extends BaseApiService {

    private static final MyLog _log = MyLog.getLog(AlizftpayApiService.class);


    @Autowired
    private Mq4AlizftpayTradeSettleConfirm mq4AlizftpayTradeSettleConfirm;

    /** 支付宝直付通二级商户进件接口 **/
    @Transactional
    public String alipayApplymentSubmit(PayAlizftMchInfo mch){

        //处理支持的支付方式
        mch.setQRPaySupport(mch.getServiceArray().indexOf("当面付") >= 0 ? MchConstant.PUB_YES: MchConstant.PUB_NO);
        mch.setAppPaySupport(mch.getServiceArray().indexOf("app支付") >= 0 ? MchConstant.PUB_YES: MchConstant.PUB_NO);
        mch.setWapPaySupport(mch.getServiceArray().indexOf("wap支付") >= 0 ? MchConstant.PUB_YES: MchConstant.PUB_NO);
        mch.setPcPaySupport(mch.getServiceArray().indexOf("电脑支付") >= 0 ? MchConstant.PUB_YES: MchConstant.PUB_NO);

        if(mch.getSubMchId() == null){  //重新插入

            PayAlizftMchInfo queryCount = new PayAlizftMchInfo(); queryCount.setCertNo(mch.getCertNo()); queryCount.setPassageTemplateId(mch.getPassageTemplateId());
            if(commonService.payAlizftMchInfoService.count(queryCount) > 0){
                return "当前数据已存在certNo的记录，请更改后再次发起提交，或关闭页面重试！";
            }

            mch.setApplyStatus(MchConstant.ALIZFT_MCH_APPLYSTATUS_NOT); //未进件状态
            mch.setStatus(MchConstant.PUB_YES); //默认开启状态
            commonService.payAlizftMchInfoService.add(mch);  //先插入记录， 避免接口调用成功 数据库插入失败的情况
        }else{

            PayAlizftMchInfo dbRecord = commonService.payAlizftMchInfoService.selectBaseInfoById(mch.getSubMchId());
            if(dbRecord == null){
                return "查询失败！";
            }
            if(dbRecord.getApplyStatus() != MchConstant.ALIZFT_MCH_APPLYSTATUS_FAIL && dbRecord.getApplyStatus() != MchConstant.ALIZFT_MCH_APPLYSTATUS_NOT){
                return "当前状态不允许再次进件！";
            }

            //更新为未进件状态 & 所有进件信息
            mch.setApplyOrderId(""); //清空 申请单
            mch.setRejectRemark(""); //清空 审核拒绝原因
            mch.setApplyQueryInfo(""); //情况 查询信息
            mch.setApplyStatus(MchConstant.ALIZFT_MCH_APPLYSTATUS_NOT); //未进件状态

            PayAlizftMchInfo condition = new PayAlizftMchInfo();
            condition.setSubMchId(mch.getSubMchId());
            int count = commonService.payAlizftMchInfoService.updateByCondition(mch, condition, Arrays.asList(MchConstant.ALIZFT_MCH_APPLYSTATUS_FAIL, MchConstant.ALIZFT_MCH_APPLYSTATUS_NOT));
            if(count <= 0){
                throw new ServiceException(RetEnum.RET_COMM_OPERATION_FAIL);
            }
        }

        PayInterfaceTypeTemplate payTemp = commonService.payInterfaceTypeTemplateService.findById(mch.getPassageTemplateId()); //查询账号模板

        JSONObject isvParam = JSONObject.parseObject(payTemp.getParamTemplate());



        AlizftpayConfig alizftpayConfig = new AlizftpayConfig(isvParam);

        try {

            //1.
            AntMerchantExpandIndirectZftCreateRequest applyRequest = new  AntMerchantExpandIndirectZftCreateRequest();

            AntMerchantExpandIndirectZftCreateModel applyModel = new AntMerchantExpandIndirectZftCreateModel();

            applyModel.setExternalId(mch.getSubMchId() + "");  //系统商户号
            applyModel.setName(mch.getName()); //商户姓名
            applyModel.setAliasName(mch.getAliasName()); //商户别名
            applyModel.setMerchantType(mch.getMerchantType()); //商户类型
            applyModel.setMcc(mch.getMccCode());  // mcc码
            applyModel.setCertType(mch.getCertType()); //证件类型
            applyModel.setCertNo(mch.getCertNo()); //证件编号
            applyModel.setLegalName(mch.getLegalName()); //法人姓名
            applyModel.setLegalCertNo(mch.getLegalCertNo()); //法人身份证号
            applyModel.setServicePhone(mch.getServicePhone());  //客户电话

            //地址信息
            AddressInfo addressInfo = new AddressInfo();
            addressInfo.setProvinceCode(mch.getProvinceCode() + "0000");  //省市县
            addressInfo.setCityCode(mch.getCityCode() + "00");
            addressInfo.setDistrictCode(mch.getDistrictCode());
            addressInfo.setAddress(mch.getAddress());  //详细地址信息
            applyModel.setBusinessAddress(addressInfo);

            //联系人信息
            ContactInfo contactInfo = new ContactInfo();
            contactInfo.setName(mch.getContactName()); contactInfo.setMobile(mch.getContactMobile()); contactInfo.setType(mch.getContactType());
            applyModel.setContactInfos(Arrays.asList(contactInfo));

            applyModel.setService(JSONArray.parseArray(mch.getServiceArray(), String.class)); //使用的服务
            applyModel.setSignTimeWithIsv(mch.getSignTimeWithIsv()); //签约时间
            applyModel.setAlipayLogonId(mch.getAlipayLogonId()); //支付宝登录账号
            applyModel.setBindingAlipayLogonId(mch.getBindingAlipayLogonId()); //支付宝签约账号

            //门头照
            if(StringUtils.isNotEmpty(mch.getOutDoorImages())){
                applyModel.setOutDoorImages(Arrays.asList(uploadImg2alipay(mch.getOutDoorImages(), alizftpayConfig)));
            }

            //营业执照图片
            if(StringUtils.isNotEmpty(mch.getCertImage())){
                applyModel.setCertImage(uploadImg2alipay(mch.getCertImage(), alizftpayConfig));
            }

            //证件反面图片
            if(StringUtils.isNotEmpty(mch.getCertImageBack())){
                applyModel.setCertImageBack(uploadImg2alipay(mch.getCertImageBack(), alizftpayConfig));
            }

            //身份证正面
            if(StringUtils.isNotEmpty(mch.getLegalCertFrontImage())){
                applyModel.setLegalCertFrontImage(uploadImg2alipay(mch.getLegalCertFrontImage(), alizftpayConfig));
            }

            //身份证反面
            if(StringUtils.isNotEmpty(mch.getLegalCertBackImage())){
                applyModel.setLegalCertBackImage(uploadImg2alipay(mch.getLegalCertBackImage(), alizftpayConfig));
            }


            //结算信息 (使用登录账号作为结算账号)
            DefaultSettleRule defaultSettleRule = new DefaultSettleRule();
            defaultSettleRule.setDefaultSettleType("alipayAccount"); defaultSettleRule.setDefaultSettleTarget(mch.getAlipayLogonId());
            applyModel.setDefaultSettleRule(defaultSettleRule);

            //网站信息
            List<SiteInfo> siteInfoList = JSONArray.parseArray(mch.getSiteArray(), SiteInfo.class);
            applyModel.setSites(siteInfoList);

            applyRequest.setBizModel(applyModel);
            AntMerchantExpandIndirectZftCreateResponse applyResponse = alipayExecute(alizftpayConfig, applyRequest);

            _log.info("applyResponse = {}", applyResponse.getBody());

            if(applyResponse.isSuccess()){ //调用成功

                PayAlizftMchInfo updateRecord = new PayAlizftMchInfo();
                updateRecord.setSubMchId(mch.getSubMchId());
                updateRecord.setApplyOrderId(applyResponse.getOrderId());  //申请单ID
                updateRecord.setApplyStatus(MchConstant.ALIZFT_MCH_APPLYSTATUS_ING); //进件中 。。.
                commonService.payAlizftMchInfoService.update(updateRecord);

                return null;

            }else{

                return String.format("errInfo=[code=%s, msg=%s, subCode=%s, subMsg=%s]", applyResponse.getCode(), applyResponse.getMsg(), applyResponse.getSubCode(), applyResponse.getSubMsg());
            }

        } catch (AlipayApiException e) {
            _log.error("支付宝进件异常", e);
            return String.format("errInfo=[code=%s, msg=%s]", e.getErrCode(), e.getErrMsg());

        } catch (Exception e) {
            _log.error("支付宝进件系统异常", e);
            return String.format("errInfo=[%s]", e.getMessage());
        }

    }

    public String queryAndUpdateStatus(Long subMchId){

        PayAlizftMchInfo mch = commonService.payAlizftMchInfoService.selectBaseInfoById(subMchId);
        if(mch.getApplyStatus() != MchConstant.ALIZFT_MCH_APPLYSTATUS_ING && mch.getApplyStatus() != MchConstant.ALIZFT_MCH_APPLYSTATUS_WAIT_SIGN){
            return "当前状态无需查询！";
        }

        PayInterfaceTypeTemplate payTemp = commonService.payInterfaceTypeTemplateService.findById(mch.getPassageTemplateId()); //查询账号模板

        AlizftpayConfig alizftpayConfig = new AlizftpayConfig(payTemp.getParamTemplate());

        try {

            //1.
            AntMerchantExpandIndirectZftorderQueryRequest applyRequest = new  AntMerchantExpandIndirectZftorderQueryRequest();
            AntMerchantExpandIndirectZftorderQueryModel applyModel = new AntMerchantExpandIndirectZftorderQueryModel();

            applyModel.setOrderId(mch.getApplyOrderId());

            applyRequest.setBizModel(applyModel);

            AntMerchantExpandIndirectZftorderQueryResponse applyResponse = alipayExecute(alizftpayConfig, applyRequest);

            _log.error("applyResponseBody = {}", applyResponse.getBody());

            if(applyResponse.isSuccess()){

                String retMsg = "查询成功！ 当前最新状态为： ";
                ZftSubMerchantOrder result = applyResponse.getOrders().get(0);

                PayAlizftMchInfo updateRecord = new PayAlizftMchInfo();
                updateRecord.appendApplyQueryInfo(mch.getApplyQueryInfo(), result);

                PayAlizftMchInfo condition = new PayAlizftMchInfo();
                condition.setApplyStatus(MchConstant.ALIZFT_MCH_APPLYSTATUS_ING);
                condition.setSubMchId(mch.getSubMchId());

                if("99".equalsIgnoreCase(result.getStatus())){ //完结状态

                    if(StringUtils.isNotEmpty(result.getSmid())){
                        updateRecord.setSmid(result.getSmid());
                    }
                    updateRecord.setApplyStatus(MchConstant.ALIZFT_MCH_APPLYSTATUS_SUCCESS);
                    retMsg += "【审核完成】";

                }else if("-1".equalsIgnoreCase(result.getStatus())){ //失败！

                    updateRecord.setApplyStatus(MchConstant.ALIZFT_MCH_APPLYSTATUS_FAIL);
                    retMsg += "【审核拒绝】";

                }else if("031".equalsIgnoreCase(result.getStatus())){ //审核中
                    retMsg += "【审核中】";
                }

                commonService.payAlizftMchInfoService.updateByCondition(updateRecord, condition, null);

                return retMsg;
            }

            return String.format("errInfo=[code=%s, msg=%s, subCode=%s, subMsg=%s]", applyResponse.getCode(), applyResponse.getMsg(), applyResponse.getSubCode(), applyResponse.getSubMsg());

            // TODO 判断进件是否成功 ...

        } catch (AlipayApiException e) {
            _log.error("查询支付宝进件异常", e);
            return String.format("errInfo=[code=%s, msg=%s]", e.getErrCode(), e.getErrMsg());

        } catch (Exception e) {
            _log.error("查询支付宝进件系统异常", e);
            return String.format("errInfo=[%s]", e.getMessage());
        }

    }


    /** 调起结算接口 **/
    public void tradeSettleConfirm(Long alizftSettRecordId){

        PayAlizftSettRecord dbRecord = commonService.payAlizftSettRecordService.findById(alizftSettRecordId);

        String payOrderId = dbRecord.getPayOrderId();
        String alipayTradeNo = dbRecord.getChannelOrderNo();

        if(dbRecord.getStatus() != MchConstant.ALIZFT_SETT_STATUS_NOT){
            _log.info("当前直付通结算记录状态非[待结算]状态 无法继续！, recordId={}", alizftSettRecordId);
            return ;
        }

        if(StringUtils.isEmpty(alipayTradeNo)){ //没有渠道订单号， 可能是补单导致， 直接更新为失败！

            _log.info("当前直付通结算记录不存在支付宝订单号无法继续！, recordId={}", alizftSettRecordId);
            String applyMsg = "错误：支付宝订单号不存在，无法完成结算任务！ 提示： 如不存在支付宝订单号且手动确认订单操作将无法正确结算，请知悉！";
            commonService.payAlizftSettRecordService.updateWait2StatusAndCountAndMsg(dbRecord, applyMsg, MchConstant.ALIZFT_SETT_STATUS_FAIL);
        }

        PayOrder payOrder = commonService.payOrderService.findByPayOrderId(payOrderId);
        PayPassageAccount payPassageAccount = commonService.payPassageAccountService.findById(payOrder.getPassageAccountId());

        AlizftpayConfig alizftpayConfig = new AlizftpayConfig(payPassageAccount.getParam());

        try {

            //1.
            AlipayTradeSettleConfirmRequest applyRequest = new  AlipayTradeSettleConfirmRequest();
            AlipayTradeSettleConfirmModel applyModel = new AlipayTradeSettleConfirmModel();

            applyModel.setOutRequestNo(payOrderId);
            applyModel.setTradeNo(alipayTradeNo);

            SettleInfo settleInfo = new SettleInfo();
            SettleDetailInfo settleDetailInfo = new SettleDetailInfo();
            settleDetailInfo.setTransInType("defaultSettle");
            settleDetailInfo.setAmount(AmountUtil.convertCent2Dollar(payOrder.getAmount().toString()));
            settleInfo.setSettleDetailInfos(Arrays.asList(settleDetailInfo));
            applyModel.setSettleInfo(settleInfo);


            applyRequest.setBizModel(applyModel);

            AlipayTradeSettleConfirmResponse applyResponse = alipayExecute(alizftpayConfig, applyRequest);

            _log.info("AlipayTradeSettleConfirmResponse = {}", applyResponse.getBody());

            if(applyResponse.isSuccess()){

                _log.info("直付通资金结算成功！ payOrderId={}", payOrderId);
                String applyMsg = String.format("trade_no:%s, out_request_no:%s, settle_amount:%s", applyResponse.getOutRequestNo(), applyResponse.getSettleAmount(), applyResponse.getTradeNo());
                commonService.payAlizftSettRecordService.updateWait2StatusAndCountAndMsg(dbRecord, applyMsg, MchConstant.ALIZFT_SETT_STATUS_SUCCESS);
            }else{

                //更新为失败状态
                String applyMsg = String.format("errInfo=[code=%s, msg=%s, subCode=%s, subMsg=%s]", applyResponse.getCode(), applyResponse.getMsg(), applyResponse.getSubCode(), applyResponse.getSubMsg());
                processApplyError(dbRecord, applyMsg);
            }

        } catch (AlipayApiException e) {
            _log.error("直付通资金结算异常", e);
            String applyMsg = String.format("errInfo=[code=%s, msg=%s]", e.getErrCode(), e.getErrMsg());
            processApplyError(dbRecord, applyMsg);

        } catch (Exception e) {
            _log.error("直付通资金结算系统异常", e);
            String applyMsg = String.format("errInfo=[msg=%s]", e.getMessage());
            processApplyError(dbRecord, applyMsg);
        }
    }

    /** 处理申请异常的情况 **/
    private void processApplyError(PayAlizftSettRecord dbRecord, String applyMsg){

        _log.error("直付通资金结算失败！！ payOrderId={}", dbRecord.getPayOrderId());
        //判断是否到达最大次数
        if(dbRecord.getRetryCount() >= 2){  //默认为0 ， 此处的2 代表最多可执行3次。
           commonService.payAlizftSettRecordService.updateWait2StatusAndCountAndMsg(dbRecord, applyMsg, MchConstant.ALIZFT_SETT_STATUS_FAIL);
            return ;

        }else{ //累加次数 重新发起结算

            commonService.payAlizftSettRecordService.updateWait2StatusAndCountAndMsg(dbRecord, applyMsg, MchConstant.ALIZFT_SETT_STATUS_NOT);
            JSONObject json = new JSONObject();
            json.put("alizftSettRecordId", dbRecord.getId());
            mq4AlizftpayTradeSettleConfirm.send(json.toString(), 10);  // TODO 由于加入多线程， 此处的延迟可能不生效。
            _log.error("直付通资金结算重新发起！！ payOrderId={}", dbRecord.getPayOrderId());
        }
    }




    /** 上传文件到阿里云服务器  返回imgID **/
    private String uploadImg2alipay(String imgPath, AlizftpayConfig config){

        try {

            AntMerchantExpandIndirectImageUploadRequest imgRequest = new AntMerchantExpandIndirectImageUploadRequest();

            String fileSuffix = FileUtils.getFileSuffix(imgPath, false).toLowerCase().trim();
            FileItem ImageContent = new FileItem(MySeq.getUUID() + "." + fileSuffix, IOUtils.toByteArray(new URL(imgPath)));
            imgRequest.setImageType(fileSuffix);
            imgRequest.setImageContent(ImageContent);

            AntMerchantExpandIndirectImageUploadResponse response = alipayExecute(config, imgRequest);

            if(response.isSuccess()){
                return response.getImageId();
            } else {

                _log.error("error, msg = {}, resp={}", response.getMsg(), response);
            }

        } catch (AlipayApiException e) {
            _log.error("AlipayApiException", e);
        }catch (Exception e) {
            _log.error("error", e);
        }

        return null;
    }

}
